package com.fita.admin.service.order.impl;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.core.persistence.support.QueryFilter;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.utils.JsonUtils;
import com.fita.admin.dao.*;
import com.fita.admin.entity.search.order.OrderSearch;
import com.fita.admin.entity.security.Login;
import com.fita.admin.handler.EhiHandler;
import com.fita.admin.handler.SmsHandler;
import com.fita.admin.service.DataServiceImpl;
import com.fita.admin.service.ShortUrlService;
import com.fita.admin.service.order.OrderService;
import com.fita.admin.web.Constant;
import com.fita.entity.agent.Agent;
import com.fita.entity.agent.AgentApply;
import com.fita.entity.agent.AgentCompany;
import com.fita.entity.data.ShortUrl;
import com.fita.entity.data.Supplier;
import com.fita.entity.dto.ehi.response.VehicleReservationCancleResponse;
import com.fita.entity.order.Order;
import com.fita.entity.order.OrderComponent;
import com.fita.entity.order.OrderStatus;
import com.fita.entity.order.PaymentRequest;
import com.fita.entity.principal.Principal;
import com.fita.entity.wallet.DistributionRewardRecord;
import com.fita.entity.wallet.UserWallet;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author 宋剑宏
 */
@Service("orderService")
public class OrderServiceImpl extends DataServiceImpl<Order> implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Dao
    private OrderDao orderDao;

    @Dao
    private PrincipalDao principalDao;

    @Autowired
    private GenericDaoSupport genericDaoSupport;

    @Dao
    private AgentDao agentDao;

    @Dao
    private AgentAuditDao agentApplyDao;

    @Dao
    private SupplierDao supplierDao;

    @Autowired
    private EhiHandler ehiHandler;

    @Autowired
    private SmsHandler smsHandler;

    @Value("#{config['wechat.host']}")
    private String wechatHost;

    @Autowired
    private ShortUrlService shortUrlService;

    @Dao
    private UserWalletDao userWalletDao;

    /*
     * (non-Javadoc)
     *
     * @see com.fita.admin.service.order.OrderService#count(com.fita.admin.entity.security.Login, com.fita.entity.order.
     * OrderStatus)
     */
    @SuppressWarnings("unchecked")
    public int count(Login login, OrderStatus status) {
        if (login.isSaleDirector()) {
            List<Agent> agents = agentDao.list(login.getDistrict());
            List<Long> aLongs = new ArrayList<Long>();
            for (Agent agent : agents) {
                aLongs.add(agent.getId());
            }
            return orderDao.count(aLongs, status);
        } else if (login.isUser()) {
            return orderDao.count(status);
        } else {
            if (agentApplyDao.listByPrincipal(genericDaoSupport.load(Principal.class, login.getId())).size() > 0) {
                List<String> mobiles = CollectionUtils.extractPropertyList(agentApplyDao.listByPrincipal(genericDaoSupport.load(Principal.class, login.getId())), "mobile");
                List<Agent> agents = agentDao.list(mobiles);
                return orderDao.countBySale(agents, status);
            }
            return 0;
        }
    }

    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#list(com.fita.admin.entity.security.Login, com.fita.entity.order.OrderStatus, com.demo2do.core.entity.page.Page)
     */
    @SuppressWarnings("unchecked")
    public List<Order> list(Login login, OrderStatus status, Page page) {
        if (login.isSaleDirector()) {
            List<Agent> agents = agentDao.list(login.getDistrict());
            List<Long> aLongs = new ArrayList<Long>();
            for (Agent agent : agents) {
                aLongs.add(agent.getId());
            }
            List<Order> orders = orderDao.listOrder(aLongs, status, page.getBeginIndex(), page.getEveryPage());
            page.calculate();
            return orders;
        } else if (login.isUser()) {
            List<Order> orders = orderDao.list(status, page.getBeginIndex(), page.getEveryPage());
            page.calculate();
            return orders;
        } else {
            List<AgentApply> agentApplies = agentApplyDao.listByPrincipal(genericDaoSupport.load(Principal.class, login.getId()));
            List<String> mobiles = CollectionUtils.extractPropertyList(agentApplies, "mobile");
            List<Agent> agents = agentDao.list(mobiles);
            List<Order> orders = orderDao.list(agents, status, page.getBeginIndex(), page.getEveryPage());
            page.calculate();
            return orders;
        }
    }

    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#count(com.fita.admin.entity.search.order.OrderSearch)
     */
    public int count(OrderSearch search) {

        String sentence = search.buildSentenceTemplate();

        Map<String, Object> parameters = search.buildParameters();

        return genericDaoSupport.count(sentence, parameters);
    }

    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#search(com.fita.admin.entity.search.order.OrderSearch, com.demo2do.core.entity.page.Page)
     */
    @SuppressWarnings("unchecked")
    public List<Order> search(OrderSearch search, Page page) {
        String sentence = search.buildSentenceTemplate();

        Map<String, Object> parameters = search.buildParameters();

        List<Order> list = genericDaoSupport.searchForList(sentence, parameters, page.getBeginIndex(), page.getEveryPage());

        page.calculate();
        return list;
    }

    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#pay(java.lang.Long)
     */
    public void pay(Long id, OrderComponent orderComponent, Long loginId) throws ParseException {

        Principal principal = genericDaoSupport.load(Principal.class, loginId);

        // 销售标记支付需要有付款图片
        if (principal.isSaler()){
            String payPic = orderComponent.getPayPic();
            if (StringUtils.isBlank(payPic)){
                throw BusinessException.newInstance("500", "付款信息图片为空");
            }
        }
        Order order = genericDaoSupport.load(Order.class, id);

        PaymentRequest paymentRequest = new PaymentRequest().generatePaymentRequest(order, orderComponent);

        genericDaoSupport.update(order.markPay(orderComponent, principal));

        genericDaoSupport.save(paymentRequest);

        String longUrl = wechatHost + "/orders/" + order.getId();

        ShortUrl orderShortUrl = shortUrlService.getByLongUrl(longUrl);

        ShortUrl pdfShortUrl = shortUrlService.getByLongUrl(order.getPdfUrl());

        String fullName = order.getCustomerName() + "/" + order.getCustomerPerfix();
        logger.info("fullname [{}]", fullName);
        logger.info("orderCode [{}]", order.getCode());
        String shortUrl = pdfShortUrl != null ? pdfShortUrl.getShortUrl() : "";
        logger.info("pdfShortUrl [{}]", shortUrl);
        String orderShortUrlShortUrl = orderShortUrl != null ? orderShortUrl.getShortUrl() : "";
        logger.info("orderShortUrl [{}]", orderShortUrl != null ? orderShortUrlShortUrl : "");

        String content = "【" + Constant.SMS_ORDER_COMPANY_NAME + "】" + fullName + "的租车订单" + order.getCode() + "已确认！取车确认书：" + wechatHost + "/" + shortUrl + "。详情请戳" + wechatHost + "/" + orderShortUrlShortUrl;

        smsHandler.sendMarkPayMessage(order.getAgent().getMobile(), content);
    }


    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#consumed(java.lang.Long)
     */
    public void consumed(Long id) {

        // 核销订单
        Order order = genericDaoSupport.load(Order.class, id);

        genericDaoSupport.update(order.consumed());

        DistributionRewardRecord distributionRewardRecord = order.getDistributionRewardRecord();

        //未核销代理奖励
        if (distributionRewardRecord.getStatus().isUnconsumed()) {
            // 核销奖励充入余额
            UserWallet userWallet = distributionRewardRecord.getTargetUserWallet();

            userWallet.consume(distributionRewardRecord.getAmount());

            genericDaoSupport.update(userWallet);

            // 核销奖励计算入一级代理总提成金额
            AgentCompany agentCompany = userWallet.getAgentCompany();

            agentCompany.addAgentCommission(distributionRewardRecord.getAmount());

            genericDaoSupport.update(agentCompany);

            //核销一级代理奖励
            distributionRewardRecord.consume(userWallet.getTotalAmount());

            genericDaoSupport.update(distributionRewardRecord);
        }


    }

    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#cancel(java.lang.Long)
     */
    @SuppressWarnings("unused")
    public void cancel(Long id) {
        Order order = genericDaoSupport.load(Order.class, id);

        if (order.getAlamoCode() == null) {

            order.cancelOrder();

        } else {

            order.cancelOrder();

            Map<String, Object> params = this.generateCancel(order);

            VehicleReservationCancleResponse response = ehiHandler.vehicleReservationCancle(params);

        }

        // 一级代理提成取消
        DistributionRewardRecord distributionRewardRecord = order.getDistributionRewardRecord();

        if (distributionRewardRecord != null) {

            distributionRewardRecord.cancel();

            genericDaoSupport.update(distributionRewardRecord);

            UserWallet targetUserWallet = distributionRewardRecord.getTargetUserWallet();

            targetUserWallet.cancelDistributionReward(distributionRewardRecord.getAmount());

            genericDaoSupport.update(targetUserWallet);
        }

        genericDaoSupport.update(order);
    }

    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#refunded(java.lang.Long)
     */
    public void refunded(Long id) {
        Order order = genericDaoSupport.load(Order.class, id);
        genericDaoSupport.update(order.refunded());
    }

    /*
     * (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#generateCancel(com.fita.entity.order.Order)
     */
    public Map<String, Object> generateCancel(Order order) {
        Supplier supplier = supplierDao.load(order.getBrand());

        if ((supplier == null || supplier.getId() == null)) {
            logger.error("generateCancel occurs error : 查询参数异常, [{}]", JsonUtils.toJson(order));
            throw BusinessException.newInstance("500", "查询参数异常");
        }

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("status", "Available");
        params.put("cancel_type", "Cancel");
        params.put("unique_id", order.getAlamoCode());
        params.put("unique_type", "14");
        params.put("given_name", order.getCustomerName());
        params.put("surname", order.getDetails().getCustomerInfo().getSurname());
        params.put("vendor_code", supplier.getPrefCode());

        logger.info("generateReservation success with result [{}]", JsonUtils.toJson(params));

        return params;
    }

    /* (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#count(com.fita.admin.entity.security.Login, java.lang.Class, com.demo2do.core.persistence.support.QueryFilter)
     */
    public int count(Login login, Class<Order> class1, QueryFilter queryFilter) {

        if (login.isSaleDirector()) {
            List<Agent> agents = agentDao.list(login.getDistrict());

            queryFilter.addSentence(" agent in (:agents) ", "agents", agents);
        }

        if (StringUtils.equals(login.getAuthority(), "SALE_USER")) {
            List<Agent> agents = listAgentByPrincipal(login.getId());

            queryFilter.addSentence(" agent in (:agents) ", "agents", agents);
        }

        return genericDaoSupport.searchForInt("SELECT COUNT(*) FROM " + ClassUtils.getShortClassName(class1) + " WHERE disabled = false" + queryFilter.clauseSentence(), queryFilter.parameters());
    }

    /* (non-Javadoc)
     * @see com.fita.admin.service.order.OrderService#search(com.fita.admin.entity.security.Login, java.lang.Class, com.fita.admin.entity.search.order.OrderSearch, com.demo2do.core.entity.page.Page)
     */
    public List<Order> search(Login login, Class<Order> class1, OrderSearch search, Page page) {

        if (login.isSaleDirector()) {

            List<Agent> agents = agentDao.list(login.getDistrict());

            search.getFilter().addSentence(" agent in (:agents) ", "agents", agents);
        }
        if (StringUtils.equals(login.getAuthority(), "SALE_USER")) {

            List<Agent> agents = listAgentByPrincipal(login.getId());

            search.getFilter().addSentence(" agent in (:agents) ", "agents", agents);
        }
        List<Order> orders = this.search(Order.class, search, page);

        return orders;
    }

    /**
     * @param principalId
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<Agent> listAgentByPrincipal(Long principalId) {

        List<AgentApply> agentApplies = agentApplyDao.listByPrincipal(genericDaoSupport.load(Principal.class, principalId));

        List<String> mobiles = CollectionUtils.extractPropertyList(agentApplies, "mobile");

        List<Agent> agents = agentDao.list(mobiles);

        return agents;
    }

}
